<template>
  <view class="content" @click="resetSlidePosition">
    <slot name="bg"></slot>
    <view
      class="box"
      :class="{ fillet: moveY > 10 + statusBarHeight, shadow: moveY > 10 + statusBarHeight }"
      :style="{
        top: HeadReservedHeight + 'px',
        transform: 'translateY(' + moveY + 'px)',
        transitionDuration: transition
      }"
      @click.stop
    >
      <view
        class="header1"
        @touchstart="touchstart"
        @touchmove="touchmove"
        @touchend="touchend"
        :class="{ fillet: moveY > 10 }"
      >
        <view class="line" v-show="moveY > 10 + statusBarHeight"> </view>
      </view>

      <scroll-view
        :scroll-y="moveY - statusBarHeight > 0 ? false : true"
        :show-scrollbar="true"
        class="scrollView"
        :scroll-with-animation="true"
        :scroll-top="scrollTop"
        @scroll="scroll"
        @touchstart="touchstart"
        @touchmove="touchmove"
        @touchend="touchend"
      >
        <view class="list">
          <!-- <view class="item" v-for="(item, index) in 100" :key="index">
            {{ item }}
          </view> -->
          <slot name="content"></slot>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps({
  HeadReservedHeight: {
    type: Number,
    default: 50
  },
  BottomReservedHeight: {
    type: Number,
    default: 200
  },
  RollingDistance: {
    type: Number,
    default: 150
  },
  Overtime: {
    type: String,
    default: '.5s'
  },
  ContentHeaderHeight: {
    type: Number,
    default: 20
  }
})
const statusBarHeight = ref(0) //状态栏高度
const moveY = ref(0) //Y轴移动的距离
const windowHeight = ref(0) //屏幕高度
// const HeadReservedHeight = ref(50) //顶部预留的高度(自定义头部高度)
// const BottomReservedHeight = ref(200) //底部预留高度
const StartingHeight = ref(0) //手指触摸开始高度
const EndHeight = ref(0) //触摸结束高度
const scrollTop = ref(0) //滚动条位置 用于判断是否开启滑动
const oldScrollTop = ref(0)
// const RollingDistance = ref(150) //滑动距离 滑动结束后超过自动滑动
const transition = ref('0s') //默认过渡时间
// const Overtime = ref('.5s') //自动滑动过渡时间

import { onLoad } from '@dcloudio/uni-app'
import { nextTick } from 'vue'
import { computed } from 'vue'
onLoad(() => {
  let _windowHeight = uni.getSystemInfoSync().windowHeight
  statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight ?? 0
  //初始化
  moveY.value = _windowHeight - props.BottomReservedHeight - props.HeadReservedHeight
  windowHeight.value = _windowHeight
})

function resetSlidePosition() {
  goTop()
  transition.value = props.Overtime
  moveY.value = windowHeight.value - props.BottomReservedHeight - props.HeadReservedHeight
}

function goTop() {
  scrollTop.value = oldScrollTop.value
  // 解决view层不同步的问题
  nextTick(function () {
    scrollTop.value = 0
  })
}
//手指触摸开始
function touchstart(e: any) {
  if (scrollTop.value != 0) {
    return
  }
  transition.value = '0s'
  StartingHeight.value = e.changedTouches[0].pageY
}

//手指触摸移动
function touchmove(e: any) {
  let pageY = e.changedTouches[0].pageY
  //滚动条不在最顶部位置不允许滑动
  if (scrollTop.value != 0) {
    return
  }
  //上滑禁止超出边界
  if (pageY <= 0 + props.HeadReservedHeight) {
    moveY.value = 0 + props.HeadReservedHeight
    return
  }
  // console.log(pageY,windowHeight - BottomReservedHeight - HeadReservedHeight)
  //下滑预留最小高度 BottomReservedHeight
  if (pageY >= windowHeight.value - props.BottomReservedHeight - props.HeadReservedHeight) {
    moveY.value = windowHeight.value - props.BottomReservedHeight - props.HeadReservedHeight
    return
  }

  moveY.value = e.changedTouches[0].pageY
}
//手指触摸结束
function touchend(e: any) {
  if (scrollTop.value != 0) {
    return
  }
  let _EndHeight = e.changedTouches[0].pageY
  EndHeight.value = _EndHeight
  let num = EndHeight.value - StartingHeight.value

  if (num >= props.RollingDistance && scrollTop.value == 0) {
    // console.log('上滑超过RollingDistance自动滑动顶部预留高度位置')
    //上滑超过RollingDistance自动滑动顶部预留高度位置
    resetSlidePosition()
  } else if (num <= -props.RollingDistance && scrollTop.value == 0) {
    // console.log('下滑超过RollingDistance自动滑动底部预留高度位置')
    //下滑超过RollingDistance自动滑动底部预留高度位置
    transition.value = props.Overtime
    moveY.value = 0 + statusBarHeight.value
  } else {
    //回弹
    transition.value = props.Overtime
    moveY.value < props.RollingDistance
      ? (moveY.value = 0 + statusBarHeight.value)
      : (moveY.value = windowHeight.value - props.BottomReservedHeight - props.HeadReservedHeight)
  }
}
//scroll-view滚动监听
function scroll(e: any) {
  oldScrollTop.value = scrollTop.value = e.detail.scrollTop
}

// == style vars ==
let contentHeaderHeight = computed(() => props.ContentHeaderHeight + 'px')
</script>

<style>
view {
  box-sizing: border-box;
}
</style>
<style lang="scss" scoped>
.fillet {
  border-top-left-radius: 30rpx;
  border-top-right-radius: 30rpx;
}

.shadow {
  box-shadow: 0rpx 0rpx 20rpx #ccc;
}

.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;

  .header_content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 30rpx;

    .return_ {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 60rpx;
      height: 60rpx;
      border-radius: 14rpx;
    }

    image {
      width: 40rpx;
      height: 40rpx;
    }
  }
}

.content {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  background-color: transparent;

  .box {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    background-color: #fff;

    .header1 {
      display: flex;
      justify-content: center;
      height: v-bind(contentHeaderHeight);
      background-color: #fff;

      .line {
        margin-top: 16rpx;
        width: 50rpx;
        height: 8rpx;
        border-radius: 4rpx;
        background-color: #d1d1d1;
      }
    }
  }

  .scrollView {
    height: 100%;

    .list {
      padding: 0 30rpx;
      width: 100%;
    }
  }
}
</style>
